package spring.security.core.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.core.Converter;

/**
 * Bean拷贝
 */
public class BeanUtils {

	private static final Map<String, BeanCopier> beanCopierMap = new HashMap<>();

	public static void copyProps(Object source, Object target) {
		copyProps(source, (Object) target, (Converter) null);
	}

	public static <T> T copyProps(Object source, Class<T> type) throws IllegalStateException {
		return (T) copyProps(source, (Class<T>) type, (Converter) null);
	}

	public static void copyProps(Object source, Object target, Converter converter) {
		if (source != null && target != null) {
			String key = generateKey(source.getClass(), target.getClass());
			BeanCopier copier = null;
			if (!beanCopierMap.containsKey(key)) {
				copier = BeanCopier.create(source.getClass(), target.getClass(), false);
				beanCopierMap.put(key, copier);
			} else {
				copier = (BeanCopier) beanCopierMap.get(key);
			}

			copier.copy(source, target, converter);
		}
	}

	public static <T> T copyProps(Object source, Class<T> type, Converter converter) throws IllegalStateException {
		if (source != null && type != null) {
			String key = generateKey(source.getClass(), type);
			BeanCopier copier = null;
			if (!beanCopierMap.containsKey(key)) {
				copier = BeanCopier.create(source.getClass(), type, false);
				beanCopierMap.put(key, copier);
			} else {
				copier = (BeanCopier) beanCopierMap.get(key);
			}

			T t = null;

			try {
				t = type.newInstance();
			} catch (IllegalAccessException | InstantiationException arg6) {
				throw new IllegalStateException("无法实例化: " + arg6);
			}

			copier.copy(source, t, converter);
			return t;
		} else {
			return null;
		}
	}

	private static String generateKey(Class<?> source, Class<?> target) {
		return source.getName() + target.getName();
	}

	public static <T> List<T> copyList(List<?> sourceList, Class<T> type) throws IllegalStateException {
		List<T> targetList = new ArrayList<T>();
		if (sourceList != null && sourceList.size() > 0 && type != null) {
			sourceList.forEach((source) -> {
				T target;
				try {
					target = type.newInstance();
				} catch (IllegalAccessException | InstantiationException arg4) {
					throw new IllegalStateException("无法实例化: " + arg4);
				}

				copyProps(source, target);
				targetList.add(target);
			});
		}

		return targetList;
	}

	public static String toString(Object obj) {
		return obj == null ? Objects.toString(obj) : ReflectionToStringBuilder.toString(obj);
	}
	
}
